dojo.provide("lotex.widget.AutoComplete");

dojo.require("dojo.dom");
dojo.require("dojo.event");
dojo.require("dojo.html.*");
dojo.require("dojo.lang.common");
dojo.require("dojo.io.*");
dojo.require("dojo.string");
dojo.require("dojo.html.style");
dojo.require("dojo.widget.HtmlWidget");

//dojo.widget.tags.addParseTreeHandler("dojo:AutoComplete");
dojo.widget.defineWidget(
    "lotex.widget.AutoComplete",
    dojo.widget.HtmlWidget,
    {
        isContainer :       true,
        widgetType :        "AutoComplete",
        key: dojo.event.browser.keys,
        // load template
        templatePath :      dojo.uri.dojoUri("../../dojo-lotex/widget/templates/AutoComplete.html"),
        templateCssPath :   dojo.uri.dojoUri("../../dojo-lotex/widget/templates/AutoComplete.css"),

        // Constants
        SELECTED_CLASS :    "selected",

        // Instance variables
        selectedNode: -1,
        action : "",
        formId : "",
        textbox : {},
        textboxId : "",
        form : {},

        postCreate:function() {
            this.form = dojo.byId(this.formId);
            this.textbox = dojo.byId(this.textboxId);

            var w = dojo.html.style.getContentWidth(this.textbox);
            var h = dojo.html.style.getContentHeight(this.textbox);
            dojo.html.style.setContentWidth(this.choices,w);
            //dojo.html.style.setContentWidth(this.domNode,w);

            var pos = dojo.html.style.abs(this.textbox);
            dojo.html.placeOnScreenPoint(this.domNode, pos.x, pos.y+h+2 , 0, false);

            dojo.event.connect(document, "onclick", this, "hide");
            dojo.event.connect(this.textbox, "onkeypress", this, "textboxOnKeyPress");
            dojo.event.connect(this.textbox, "onkeydown", this, "textboxOnKeyDown");
            dojo.event.connect(this.textbox, "onkeyup", this, "textboxOnKeyUp");
            this.bgIframe = new dojo.html.BackgroundIframe(this.domNode);
            this.bgIframe.onResized();
        },

        // If a form submission via enter is detected while the choices are being displayed, dont't
        // submit the form and close the choices div.  Give focus to the next form element.
        textboxOnKeyPress : function(evt) {
            if(!this.isShowing()) return;
            if(evt.keyCode == this.key.KEY_ENTER ||
               evt.keyCode == this.key.KEY_SPACE){
                this.setValue(this.getSelected());
                this.hide();
                evt.preventDefault();
                for (var i=0; i<this.form.elements.length; i++) {
                    if (this.textbox.name == this.form.elements[i].name && (i+1 < this.form.elements.length)) {
                        this.form.elements[i+1].focus();
                        break;
                    }
                }
            }
        },

        // Check for tab key which is detected on "keyDown" event and not "keyUp"
        textboxOnKeyDown : function(evt) {
            if (this.isShowing() && evt.keyCode == 9) {
                this.hide();
            }
        },

        // Convenience function that checks if the first argument is repeated in subsequent ones
        isKey : function () {
            if (arguments.length < 2) return false;
            for (var i=1;i<arguments.length;i++) {
                if (arguments[0] == arguments[i]) return true;
            }
            return false;
        },

        // If up or down arrow is pressed, call this.checkUpDownArrows, otherwise get latest list
        textboxOnKeyUp : function(evt) {
            if (this.isKey(evt.keyCode, 38, 40)) {
                this.checkUpDownArrows(evt.keyCode);
            } else if (this.isKey(evt.keyCode, 49,50,51,52,53,54,55,56,57)) {
                this.setValue(evt.keyCode - 49);
                this.hide();
                // TODO add if when data length > 0, num key use as input code
            } else {
                bindArgs = {
                    url:        this.action,
                    mimetype:   "text/javascript",
                    formNode:   this.form
                };
                var req = dojo.io.bind(bindArgs);
                dojo.event.connect(req, "load", this, "populateChoices");
            }
        },


        // If up or down arrow is pressed, select approriate element
        checkUpDownArrows : function(characterCode) {
            if (!this.isShowing()) return;

            var selIndex = this.selectedNode;
            if (selIndex == -1) {
                if (characterCode == 38) {
                    this.swapSelectedTo(this.maxRowIndex);
                } else if (characterCode == 40){
                    this.swapSelectedTo(0);
                }
            } else if (characterCode == 38) {
                 if (selIndex-1 >= 0) {
                    this.swapSelectedTo(selIndex-1);
                 } else if (this.maxRowIndex > 0) {
                    this.swapSelectedTo(this.maxRowIndex);
                 }
            } else if (characterCode == 40) {
                 if (selIndex+1 <= this.maxRowIndex) {
                    this.swapSelectedTo(selIndex+1);
                 } else {
                    this.swapSelectedTo(0);
                 }
            }
        },

        // Returns the index of the div that is selected.  Returns -1 if nothing is selected
        getSelected : function() {
            return this.selectedNode;
        },


        addRow : function(data) {
          var rowIndex = this.choices.rows.length+1;
          //if(rowIndex>9)return;

          var tr = document.createElement("tr");

          var td = document.createElement("td");
          td.innerHTML = "<u>"+rowIndex+"</u>";
          tr.appendChild(td);
            for (var i=0; i<data.length; i++) {
                var td = document.createElement("td");
                td.innerHTML = data[i];
                tr.appendChild(td);
            }
            dojo.event.connect(tr, "onmouseover", this, "itemOnMouseOver");
            dojo.event.connect(tr, "onclick", this, "itemOnClick");
            this.choices.tBodies[0].appendChild(tr);
        },


        // Handler for "load" action of dojo.io.bind() call.  Puts choices into div
        populateChoices : function(type, data, evt) {
            this.clearChoices();
            this.length = data.length;
            if (this.length <= 0) {
                this.hide();
                return;
            }

            for (var i=0; i<this.length; i++) {
                this.addRow(data[i]);
            }
            this.maxRowIndex = this.length - 1;
            this.selectedNode = this.maxRowIndex;
            this.show();
            dojo.html.style.setContentHeight(this.domNode,dojo.html.style.getContentHeight(this.choices));
            this.bgIframe.onResized();
            this.swapSelectedTo(0);
        },

        clearChoices : function() {
            //this.choices.tBodies[0].innerHTML = "<tr><td></td></tr>";
            var rowNum = this.choices.rows.length;
            if (rowNum<=0) return;
            for (var i=0; i<rowNum; i++) {
                    this.choices.deleteRow(0);
            }
        },

        itemOnMouseOver: function(/* DomEvent */ e) {
            var row=dojo.html.getParentByType(e.target,"tr");
            this.swapSelectedTo(row.rowIndex);
        },

        itemOnClick: function(/* DomEvent */ e) {
            var row=dojo.html.getParentByType(e.target,"tr");
            this.swapSelectedTo(row.rowIndex);
            this.hide();
        },

        swapSelectedTo: function(/* Integer */ idx) {
            if(idx<0 || idx==this.selectedNode) return;

            if(this.selectedNode>=0) this.choices.rows[this.selectedNode].className = "";
            this.choices.rows[idx].className = this.SELECTED_CLASS;
            this.selectedNode = idx;
        },

        setValue: function(/* Integer */ idx) {
            this.textbox.value = this.getValue(idx);
        },

        getValue: function(/* Integer */ idx) {
            // TODO 3 to arg..
            return this.choices.rows[idx].cells[3].innerHTML;
        },

        onHide: function(evt){
            if(this.selectedNode>=0 && this.selectedNode<this.length) this.setValue(this.selectedNode);
            lotex.widget.AutoComplete.superclass.onHide.call(this);
            this.selectedNode = -1;
            // TODO destroy function
        }
    }
);